﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using KL.UFrame.Core.Configuration;
using KL.UFrame.Core.Exception;
using KL.UFrame.Core.Result;
using Newtonsoft.Json;

namespace KL.UFrame.Api.ApiControllers
{
    public class FileController : K9ApiBaseController
    {
        private static decimal _maxFileM = AppConfiguration.FileUploadMaxLength/1048576M;
        private static ResultMessage _maxFileLengError = new ResultMessage(-1, "文件大小不能超过" + _maxFileM + "M");

        /// <summary>
        /// 使用字节上传文件
        /// </summary>
        /// <param name="ext">文件扩展名</param>
        /// <returns></returns>
        public async Task<ResultMessage> Post(string ext)
        {
            var result = new ResultMessage();
            try
            {
                var file = await Request.Content.ReadAsByteArrayAsync();
                if (file.Length > AppConfiguration.FileUploadMaxLength)
                {
                    return _maxFileLengError;
                }
                var fileName = Guid.NewGuid().ToString("n") + "." + ext;
                string strPath = HttpContext.Current.Server.MapPath("~/" + AppConfiguration.ProfileUploadPath + fileName);
                using (var writer = new FileStream(strPath, FileMode.CreateNew))
                {
                    writer.Write(file, 0, file.Length);
                }

                result.Message = AppConfiguration.ProfileUploadPath + fileName;
            }
            catch (Exception ex)
            {
                result.Code = -10;
                result.Message = "上传文件失败";
            }

            return result;
        }

        /// <summary>
        /// 无分块上传
        /// </summary>
        /// <returns></returns>
        public async Task<ResultMessage> Post()
        {
            try
            {
                var postString = await Request.Content.ReadAsStringAsync();
                if (postString == null)
                {
                    throw new ResultException(-501,"未上传有效数据");
                }
                var url = await SaveAsync(postString);
                return new ResultMessage(0, url);
            }
            catch
            {
                throw;
            }
        }

        private static readonly Regex ExtReg = new Regex("^data:.+/(?<ext>.+);base64");


        /// <summary>
        /// 从base64中获取文件扩展名
        /// </summary>
        /// <param name="base64FileCode"></param>
        /// <returns></returns>
        private static string GetExtFromBase64(string base64FileCode)
        {
            if (ExtReg.IsMatch(base64FileCode))
            {
                return ExtReg.Match(base64FileCode).Result("${ext}");
            }
            return null;
        }
        /// <summary>
        /// 将base64格式的文件保存到服务器
        /// </summary>
        /// <param name="base64FileCode"></param>
        /// <param name="ext">文件扩展名，若不传入将从base64FileCode读取</param>
        /// <returns>文件的相对目录</returns>
        /// <returns></returns>
        public async Task<string> SaveAsync(string base64FileCode, string ext = null)
        {
            if (string.IsNullOrEmpty(ext))
            {
                //没有提供扩展名，从base64FileCode读取：data:image/png;base64,

                ext = GetExtFromBase64(base64FileCode);
                if (string.IsNullOrEmpty(ext))
                {
                    throw new ResultException(-500, "请提供有效的文件扩展名");
                }
            }

            byte[] bytes = null;
            var extraMsgIndex = base64FileCode.IndexOf("base64,");
            if (extraMsgIndex >= 0)
            {
                bytes = Convert.FromBase64String(base64FileCode.Remove(0, extraMsgIndex + 7));
            }
            else
            {
                bytes = Convert.FromBase64String(base64FileCode);
            }
            if (!ext.StartsWith(".")) ext = "." + ext;

            var directory = AppConfiguration.FileUploadPath + GetMonth()+"/";

            var directoryPath = HttpContext.Current.Server.MapPath("~/" + directory);

            if (!Directory.Exists(directoryPath))
            {
                Directory.CreateDirectory(directoryPath);
            }

            var name = directory + Guid.NewGuid().ToString("n") + ext;

            var uploadPath = HttpContext.Current.Server.MapPath("~/" + name);

            using (var fs = new FileStream(uploadPath, FileMode.Create))
            {
                await fs.WriteAsync(bytes, 0, bytes.Length);
            }
            return name;
        }

        private static int GetMonth(DateTime? time=null)
        {
            if(time==null) time = DateTime.Now;
            return time.Value.Year*100 + time.Value.Month;
        }
    }
}
